import Cesium, { Event } from '../Ces/Cesium'
import Config from './Config'
import WeTaskProcessorPool from './WeTaskProcessorPool'

const WeResourceWindSymbolTexture = 'wind_symbol'
const WeResourceWindTailTexture = 'wind_tail'

class WeContext {
  private loadings = {}
  private textures = {}
  private reousrces = {}
  private _taskProcessorPool: WeTaskProcessorPool

  private _event: Event

  get taskProcessorPool() {
    if (!this._taskProcessorPool) {
      this._taskProcessorPool = new WeTaskProcessorPool()
    }
    return this._taskProcessorPool
  }

  get loadingEvent() {
    if (!this._event) {
      this._event = new Cesium.Event()
    }
    return this._event
  }

  reqisterImage(key, url) {
    if (this.reousrces[key]) return
    this.reousrces[key] = url
    this.loadings[key] = false
  }

  enableWindTail() {
    if (this.reousrces[WeResourceWindTailTexture]) return
    this.reqisterImage(WeResourceWindTailTexture, Config.windTailImage)
  }

  get windTailTexture() {
    return this.textures[WeResourceWindTailTexture]
  }

  enableWindTexture() {
    if (this.reousrces[WeResourceWindSymbolTexture]) return
    const url = Cesium.buildModuleUrl('we-assets/textures/wind_symbol.png')
    this.reqisterImage(WeResourceWindSymbolTexture, url)
  }

  get windSymbolTexture() {
    return this.textures[WeResourceWindSymbolTexture]
  }

  private loadResource(key, context) {
    this.loadings[key] = true
    const url = this.reousrces[key]
    const promise = url instanceof Promise ? url : Cesium.Resource.fetchImage(url)
    promise
      .then((image) => {
        this.textures[key] = new Cesium.Texture({
          context,
          source: image,
          flipY: false,
        })
      })
      .catch(() => {
        throw url
      })
      .finally(() => {
        this.loadings[key] = false
      })
  }

  update(frameState) {
    if (!frameState.passes.render) return

    Object.keys(this.loadings).forEach((key) => {
      if (!this.loadings[key] && !this.textures[key]) {
        this.loadResource(key, frameState.context)
      }
    })

    frameState.context.weContext = this
  }

  isDestroyed() {
    return false
  }

  destroy() {
    this._taskProcessorPool = this._taskProcessorPool && this._taskProcessorPool.destroy()
    Object.values(this.textures).forEach((obj: any) => {
      obj.destroy()
    })
    this.textures = {}
    return Cesium.destroyObject(this)
  }
}

export default WeContext
